﻿namespace TestApp.DataService
{
    using System;
    using System.Collections.Generic;
    using System.Diagnostics.Contracts;
    using System.Linq;
    using Contracts;
    using JetBrains.Annotations;

    internal sealed class DataStore : IDataStore
    {
        private readonly object _lockObject = new object();
        private readonly DataEntityDto[] _dataEntities = new DataEntityDto[DataEntityDto.EntityCount];
        private readonly long[] _dataVersions = new long[DataEntityDto.EntityCount];
        private long _curVersion;

        public bool TryGetDataEntities(long version, out long dataVersion, out IEnumerable<DataEntityDto> entities)
        {
            Contract.Requires<ArgumentOutOfRangeException>(version >= 0);
            lock (_lockObject)
            {
                dataVersion = _curVersion;
                if (version >= _curVersion)
                {
                    entities = null;
                    return false;
                }

                entities = Array.AsReadOnly(GetDataEntities(version).ToArray());
            }

            return entities.Any();
        }

        public void SaveDataEntity(DataEntityDto entity)
        {
            Contract.Requires<ArgumentNullException>(entity != null);
            lock (_lockObject)
            {
                _curVersion++;
                _dataEntities[entity.Index] = entity;
                _dataVersions[entity.Index] = _curVersion;
            }
        }

        [NotNull] private IEnumerable<DataEntityDto> GetDataEntities(long version)
        {
            for (var index = 0; index < _dataVersions.Length; index++)
            {
                if (_dataVersions[index] <= version)
                {
                    continue;
                }

                yield return _dataEntities[index];
            }
        }
    }
}